<?php
namespace app\app\model;

use think\Model;
use think\Config;

class App extends Model {
    protected $pk = 'appid';

    private $_iv = null;
    private $_key = null;

    /**
     * 生成应用的通信密钥
     * @return string 通信密钥
     */
    public static function generateSecret(){
        $hash = hash_hmac('sha256', uniqid(), config('app.baseKey'), true);
        $iv = bin2hex(substr($hash, 0, 8));
        $key = substr(base64_encode(substr($hash, 8)), 0, 32);
        return $key . $iv;
    }

    /**
     * 获取应用列表，排除某些应用
     * @param array $except 要排除的应用name的列表
     * @return App[] 筛选后的应用列表
     */
    public static function getSiteExcept($except){
        if(!is_string($except)){
            $except = [$except];
        }
        return self::where([
            ['name', 'not in', $except],
            ['sync_login', '=', 1],
        ])->select();
    }

    /**
     * 获取同步登录的url
     * @param int $uid - 用户id
     * @param string $except - 排除的网站
     */
    public static function getSyncLoginUrl($uid, $rememberLogin = false, $except = []){
        $data = [
            'uid' => $uid,
            'remember' => $rememberLogin,
            'expire' => time() + Notice::EXPIRE,
        ];
        $results = [];

        $cond = [
            ['sync_login', '=', 1],
        ];
        if(count($except) > 0){
            $cond[] = ['name', 'not in', $except];
        }
        $sites = self::where($cond)->select();
        
        foreach($sites as $site){
            $code = base64_encode_url($site->encrypt($data));
            $url = $site->fronted_api_url;
            if(strpos($url, '?') === false){
                $url .= '?code=' . $code;
            } else {
                $url .= '&code=' . $code;
            }
            $results[] = $url;
        }

        return $results;
    }

    public function getIvAttr($data, $value){
        if(!$this->_iv){
            $this->_iv = substr($value['secret'], 32, 16);
        }
        return $this->_iv;
    }

    public function getKeyAttr($data, $value){
        if(!$this->_key){
            $this->_key = substr($value['secret'], 0, 32);
        }
        return $this->_key;
    }

    /**
     * 加密数据
     * @param array $json - 要加密的数据
     * @return string 加密结果（二进制）
     */
    public function encrypt($json){
        $data = json_encode($json);
        $iv = $this->getAttr('iv');
        $key = $this->getAttr('key');
        return openssl_encrypt($data, 'aes-256-cbc', $key, OPENSSL_RAW_DATA, $iv);
    }

    /**
     * 解密数据
     * @param string $bin - 要解密的数据
     * @return array 解密结果
     */
    public function decrypt($bin){
        $iv = $this->getAttr('iv');
        $key = $this->getAttr('key');
        $data = openssl_decrypt($bin, 'aes-256-cbc', $key, OPENSSL_RAW_DATA, $iv);
        if($data){
            return json_decode($data, true);
        } else {
            return false;
        }
    }
}